热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

电压|笔者_基于28035的ePWM触发ADC采样设计

篇首语:本文由编程笔记#小编为大家整理,主要介绍了基于28035的ePWM触发ADC采样设计相关的知识,希望对你有一定的参考价值。目录

篇首语:本文由编程笔记#小编为大家整理,主要介绍了基于28035的ePWM触发ADC采样设计相关的知识,希望对你有一定的参考价值。



目录


    • 前言
    • 实验目的
    • 实验要求
    • 硬件电路
    • 实验步骤
    • 代码解释
    • 实验结果
    • 总结
    • 体会



前言

玖道最近在做一个开关电源项目,需要用到TI 的TMS320F28035 芯片,实现控制电路的设计。简单来说就是利用28035采集信号量,经过算法计算,得到占空比,然后利用ePWM模块输出PWM波来控制功率开关管的导通和关断,从而实现拓扑的功率变换。

为了实现控制,我们需要在一个开关周期(PWM周期)内实现ADC采样,占空比计算等。那么,如何实现在每个开关周期内进行ADC采样呢?

答案是利用ePWM模块在每个PWM周期内去触发ADC模块进行采样,那究竟如何配置实现?

这就是本文要讲的主题了~


实验目的

通过ePWM模块和ADC模块,实现ePWM在每个PWM周期内发出SOC(start of conversion)信号,触发ADC进行采样,以此深入理解两个模块的工作原理与配置细节。


实验要求

如下图所示,通过ePWM模块产生固定频率和占空比的PWM信号,并在每个PWM周期开始处进行采样,即采样频率等于PWM频率。


硬件电路

如下图所示,ADC通过RG引脚采样可调电阻的电压值,并保存在结果寄存器ADCRESULT中。跳线帽短接3-5脚,可变电阻的电压值通过RGADIN0B相连,即ADC可通过ADIN0B对可变电阻值进行采样。这里的ADIN0B指的是ADC 16路复用输入通道中的GROUP B channel 0。具体如下图所示。




注意,ADCINB0就是一个ADC输入采样引脚,并不是通过GPIO进行复用的,所以并不需要配置GPIO,直接使用就行。


实验步骤


整个系统的程序流程图,大致如上图所示。

首先,是DSP系统的一些初始化操作,包括锁相环,看门狗,外设时钟使能,关闭中断,初始化PIE中断向量表等。

其次,就是配置EPWM模块,产生固定频率和占空比的PWM,并设置触发EPWMxSOCA(或EPWMxSOCB,这里选择EPWMxSOCA)信号。

然后,ADC模块配置采样输入通道,触发源(接收EPWMxSOCA),采样窗的大小,并选择某个SOCx(x:0-15,这里选择SOC1)进行ADC转换和触发中断ADCINTx(x:1-9)

最后,就是进入循环,进行喂狗,显示等其他后台操作。发生ADC中断时,进入ADC中断服务函数,取出可变电阻采样值并保存到数组中。

大致流程就是这样,当然读懂的前提是充分了解28035的EPWM模块和ADC模块,即熟读TI官方的用户手册和数据手册。

另外,这里面还有很多细节,未曾提及,主要还是参考官方例程和芯片手册,然后结合需求进行修改。


代码解释


#include "DSP28x_Project.h" // Device Header file and Examples Include File
// Prototype statements for functions found within this file.
__interrupt void adc_isr(void);
// Global variables used in this example:
Uint16 ConversionCount;
Uint16 Voltage1[10];
int main()

// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2803x_SysCtrl.c file.
InitSysCtrl();
// Step 2. Initialize GPIO:
// This example function is found in the DSP2803x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio(); // Skipped for this example
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP2803x_PieCtrl.c file.
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in DSP2803x_DefaultIsr.c.
// This function is found in DSP2803x_PieVect.c.
InitPieVectTable();
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected register
PieVectTable.ADCINT1 = &adc_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
// Step 4. Initialize all the Device Peripherals:
InitAdc(); // For this example, initialize the ADC
AdcOffsetSelfCal();
// Step 5. User specific code, enable interrupts:
// Enable ADCINT1 in PIE
PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable INT 1.1 in the PIE for ADCINT1
IER |= M_INT1; // Enable CPU Interrupt 1
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global real time interrupt DBGM
ConversionCount = 0;
// Configure ADC
// Note: Channel ADCINB0 will be double sampled to workaround the ADC 1st sample issue for rev0 silicon errata
EALLOW;
AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; //ADCINT1 trips after AdcResults latch
AdcRegs.INTSEL1N2.bit.INT1E = 1; //Enabled ADCINT1
AdcRegs.INTSEL1N2.bit.INT1CONT = 0; //Disable ADCINT1 Continuous mode
AdcRegs.INTSEL1N2.bit.INT1SEL = 1; //setup EOC1 to trigger ADCINT1 to fire
AdcRegs.ADCSOC0CTL.bit.CHSEL = 8; //set SOC0 channel select to ADCINB0(dummy sample for rev0 errata workaround)
AdcRegs.ADCSOC1CTL.bit.CHSEL = 8; //set SOC1 channel select to ADCINB0
AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5; //set SOC0 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5; //set SOC1 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; //set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
AdcRegs.ADCSOC1CTL.bit.ACQPS = 6; //set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
EDIS;
// Assumes ePWM1 clock is already enabled in InitSysCtrl();
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group
EPwm1Regs.ETSEL.bit.SOCASEL = 1; // generate SOCx when TBCTR = ZERO
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
EPwm1Regs.CMPA.half.CMPA = 0x0080; // Set compare A value
EPwm1Regs.TBPRD = 0xFFFF; // Set period for ePWM1
EPwm1Regs.TBCTL.bit.CTRMODE = 0; // count up and start
// Wait for ADC interrupt
for(;;)



__interrupt void adc_isr(void)

Voltage1[ConversionCount] = AdcResult.ADCRESULT1; //discard ADCRESULT0 as part of the workaround to the 1st sample errata for rev0
// If 20 conversions have been logged, start over
if(ConversionCount == 9)

ConversionCount = 0;

else

ConversionCount++;

AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Clear ADCINT1 flag reinitialize for next SOC
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE
return;


实验结果

编辑好代码后,烧录到芯片中,然后Debug,全速运行,通过窗口[Window->show view->expression]添加采样值。可以看到,10个采样值在实时进行刷新,即实现了PWM触发ADC周期性采样。


总结

本文简单介绍了利用TMS320F28035的EPWM模块产生SOC信号,以此触发ADC模块进行采样的大致设计思路及流程,并结合官方例程给出相应代码和实验结果,其中并未详细讲述EPWM模块和ADC模块相关寄存器的具体配置过程,读者可参考TI官方手册:


  • 2803x Piccolo Technical Reference Manual.pdf
  • tms320f28035.pdf

体会

笔者认为学习DSP最好的方式就是:官方例程+数据手册+用户手册+开发板+CCS。

具体来讲呢,官方例程可以给我们提供一个程序正确的整体架构,比如一些初始化步骤,先初始化哪部分,然后再初始化哪部分,最后再怎么样。

数据手册+用户手册可以说是最重要的资料了,必须要反复研读英文原版(记住是英文版,中文版可能会有很多翻译错误,笔者踩过坑),而且最好是结合代码研读,并做好笔记,方便以后复习。

配合数据手册和用户手册将官方例程看懂之后,就可以进行自己的一些配置了,从底层新建工程,一步一步编写自己的代码,然后结合CCS+开发板进行调试。

调试代码的时间可能是编写代码所费时间的数倍不止,因为程序会有很多Bug,这个时候就要结合数据手册和用户手册,对代码进行一行一行的检查,弄懂每一行代码的作用,思考逻辑或寄存器配置是否错误。

当你从头到尾,成功完成一个小实验,实现理论到实验验证的闭环,相信你的能力和信心会提高不少。


推荐阅读
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • 开发笔记:计网局域网:NAT 是如何工作的?
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了计网-局域网:NAT是如何工作的?相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 如何在php中将mysql查询结果赋值给变量
    本文介绍了在php中将mysql查询结果赋值给变量的方法,包括从mysql表中查询count(学号)并赋值给一个变量,以及如何将sql中查询单条结果赋值给php页面的一个变量。同时还讨论了php调用mysql查询结果到变量的方法,并提供了示例代码。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有